﻿using System;
using System.Threading.Tasks;
using lctdevice;
using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Equipment.Interfaces.Communication;
using RotovapPlatform.Domain.Equipment.Interfaces.Services;

namespace RotovapPlatform.Infrastructure.Equipment.Devices.IO
{
	/// <summary>
	/// IO模块服务实现类
	/// 基于EtherCAT通信实现IO设备访问
	/// </summary>
	public class IOModuleService : IIOModuleService
	{
		private readonly IEtherCATManager _etherCATManager;
		private readonly ILogger<IOModuleService> _logger;

		// 冷凝器压力传感器配置
		private const int CondenserPressureChannel = 0;
		private const double CondenserPressureMinValue = -100;
		private const double CondenserPressureMaxValue = 100; // (-100～100kPa)

		/// <summary>
		/// 构造函数
		/// </summary>
		public IOModuleService(IEtherCATManager etherCATManager, ILogger<IOModuleService> logger)
		{
			_etherCATManager = etherCATManager ?? throw new ArgumentNullException(nameof(etherCATManager));
			_logger = logger ?? throw new ArgumentNullException(nameof(logger));
		}

		/// <summary>
		/// 读取所有DI信号状态
		/// </summary>
		public async Task<int> ReadAllDIAsync()
		{
			try
			{
				uint value = 0;
				short ret = ecat_motion.M_Get_Digital_Port_Input(1, ref value, _etherCATManager.CardId);
				if (ret == 0)
					_logger.LogDebug("读取从站中从第1个DI通道开始往后共32个DI通道的数值", ret);

				return (int)value;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "读取所有DI信号状态失败");
				return 0;
			}
		}


		/// <summary>
		/// 写入指定DO信号状态
		/// </summary>
		public async Task<bool> WriteDOAsync(int channel, bool state)
		{
			try
			{
				// 确保通道号从1开始 (不需要+1，因为传入的channel已经是从1开始)
				short value1 = state ? (short)1 : (short)0;
				short ret = ecat_motion.M_Set_Digital_Chn_Output((short)channel, value1, _etherCATManager.CardId);
				_logger.LogDebug("设置从站中第" + channel + "个DO通道的数值为" + value1, ret);

				short value2 = 0;
				ret += ecat_motion.M_Get_Digital_Chn_Output((short)channel, out value2, _etherCATManager.CardId);
				if (ret == 0 && value2 == (state ? (short)1 : (short)0))
					_logger.LogDebug("读取从站中第" + channel + "个DO通道的数值", ret);
				return true;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"写入DO信号({channel})状态失败");
				return false;
			}
		}


		/// <summary>
		/// 读取指定DO信号状态（回读）
		/// </summary>
		public async Task<bool> ReadDOAsync(int channel)
		{
			try
			{
				short value = 0;
				short ret = ecat_motion.M_Get_Digital_Chn_Output((short)channel, out value, _etherCATManager.CardId);
				if (ret == 0)
					_logger.LogDebug("读取从站中第" + channel + "个DO通道的数值", ret);
				return true;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"读取DO信号({channel})状态失败");
				return false;
			}
		}

		/// <summary>
		/// 读取模拟输入信号值
		/// </summary>
		public async Task<double> ReadAIAsync(int channel)
		{
			try
			{
				short count = 2;//这里以一次性读取2通道模拟量输入举例
				short[] value = new short[2];//所以该数组的长度为2
				short ret = ecat_motion.M_Get_Analog_Input(1, out value[0], count, _etherCATManager.CardId);
				if (ret == 0)
					_logger.LogDebug("读取从站中从第" + channel + "个AI通道开始往后共2路模拟量输入通道的数值", ret);
				return value[0];
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"读取AI信号({channel})值失败");
				return 0;
			}
		}

		/// <summary>
		/// 获取冷凝器压力值（模拟信号）
		/// </summary>
		public async Task<double> GetCondenserPressureAsync()
		{
			try
			{
				// 读取模拟输入通道值，并转换为工程单位
				double rawValue = await ReadAIAsync(CondenserPressureChannel);

				// 这里简单模拟压力值在-100-100kPa之间 对应4-20mA
				//0 ~ 20ma 对应数字量 0 ~ +32767
				//4 ~ 20ma 对应数字量 6553 ~ +32767
				//0 ~ 4ma 对应数字量 0 ~ 6553
				// 计算压力值
				double pressure = (rawValue - 6553) * (CondenserPressureMaxValue - CondenserPressureMinValue) / (32767 - 6553) + CondenserPressureMinValue;
				return Math.Max(CondenserPressureMinValue,
					Math.Min(CondenserPressureMaxValue, pressure));
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "获取冷凝器压力值失败");
				return 0;
			}
		}
	}
}